use criterion::{black_box, criterion_group, criterion_main, Criterion};
use list::list::*;
use std::ffi::c_void;

fn list_benchmark(c: &mut Criterion) {
    c.bench_function("list_list_prepend", |b| {
        b.iter(|| {
            let mut list: *mut ListEntry = std::ptr::null_mut();
            unsafe {
                list_prepend(&mut list, black_box((&42 as *const i32) as *const c_void));
            }
        })
    });

    c.bench_function("list_list_append", |b| {
        b.iter(|| {
            let mut list: *mut ListEntry = std::ptr::null_mut();
            unsafe {
                list_append(&mut list, black_box(&42 as *const c_void));
            }
        })
    });

    c.bench_function("list_list_nth_entry", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, (&42 as *const i32) as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, (&44 as *const i32) as *const c_void);
        }
        b.iter(|| {
            unsafe {
                list_nth_entry(black_box(list), black_box(1));
            }
        })
    });

    c.bench_function("list_list_nth_data", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, (&43 as *const i32) as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        b.iter(|| {
            unsafe {
                list_nth_data(black_box(list), black_box(1));
            }
        })
    });

    c.bench_function("list_list_remove_entry", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            let entry = list_append(&mut list, (&42 as *const i32) as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, (&44 as *const i32) as *const c_void);
            b.iter(|| {
                list_remove_entry(&mut list, black_box(entry));
            })
        }
    });

    c.bench_function("list_list_remove_data", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
            b.iter(|| {
                list_remove_data(
                    &mut list,
                    black_box(|a, b| a == b),
                    black_box(&42 as *const c_void),
                );
            })
        }
    });

    c.bench_function("list_list_length", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
            list_append(&mut list, (&42 as *const i32) as *const c_void);
        }
        b.iter(|| {
            unsafe {
                list_length(black_box(list));
            }
        })
    });

    c.bench_function("list_list_sort", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, (&42 as *const i32) as *const c_void);
            list_append(&mut list, (&44 as *const i32) as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        b.iter(|| {
            unsafe {
                list_sort(
                    &mut list,
                    black_box(|a, b| (a as usize).cmp(&(b as usize))),
                );
            }
        })
    });

    c.bench_function("list_list_iter_remove", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        let mut iter = ListIterator {
            prev_next: std::ptr::null_mut(),
            current: std::ptr::null_mut(),
        };
        unsafe {
            list_iterate(&mut list, &mut iter);
            list_iter_next(&mut iter);
        }
        b.iter(|| {
            unsafe {
                list_iter_remove(&mut iter);
            }
        })
    });

    c.bench_function("list_list_to_array", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        b.iter(|| {
            unsafe {
                list_to_array(black_box(list));
            }
        })
    });

    c.bench_function("list_list_find_data", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, (&43 as *const i32) as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        b.iter(|| {
            unsafe {
                list_find_data(
                    black_box(list),
                    black_box(|a, b| a == b),
                    black_box(&42 as *const c_void),
                );
            }
        })
    });

    c.bench_function("list_list_iterate", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, (&42 as *const i32) as *const c_void);
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, (&44 as *const i32) as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        let mut iter = ListIterator {
            prev_next: std::ptr::null_mut(),
            current: std::ptr::null_mut(),
        };
        b.iter(|| {
            unsafe {
                list_iterate(&mut list, &mut iter);
            }
        })
    });

    c.bench_function("list_list_iter_next", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, (&43 as *const i32) as *const c_void);
        }
        let mut iter = ListIterator {
            prev_next: std::ptr::null_mut(),
            current: std::ptr::null_mut(),
        };
        unsafe {
            list_iterate(&mut list, &mut iter);
        }
        b.iter(|| {
            unsafe {
                list_iter_next(&mut iter);
            }
        })
    });

    c.bench_function("list_list_iter_has_more", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, (&42 as *const i32) as *const c_void);
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, (&44 as *const i32) as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        let mut iter = ListIterator {
            prev_next: std::ptr::null_mut(),
            current: std::ptr::null_mut(),
        };
        unsafe {
            list_iterate(&mut list, &mut iter);
        }
        b.iter(|| {
            unsafe {
                list_iter_has_more(&mut iter);
            }
        })
    });
}

criterion_group!(benches, list_benchmark);
criterion_main!(benches);
use list::list::*;
use std::ffi::c_void;

fn list_benchmark(c: &mut Criterion) {
    c.bench_function("list_list_prepend", |b| {
        b.iter(|| {
            let mut list: *mut ListEntry = std::ptr::null_mut();
            unsafe {
                list_prepend(&mut list, black_box((&42 as *const i32) as *const c_void));
            }
        })
    });

    c.bench_function("list_list_append", |b| {
        b.iter(|| {
            let mut list: *mut ListEntry = std::ptr::null_mut();
            unsafe {
                list_append(&mut list, black_box(&42 as *const c_void));
            }
        })
    });

    c.bench_function("list_list_nth_entry", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, (&42 as *const i32) as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, (&44 as *const i32) as *const c_void);
        }
        b.iter(|| {
            unsafe {
                list_nth_entry(black_box(list), black_box(1));
            }
        })
    });

    c.bench_function("list_list_nth_data", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, (&43 as *const i32) as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        b.iter(|| {
            unsafe {
                list_nth_data(black_box(list), black_box(1));
            }
        })
    });

    c.bench_function("list_list_remove_entry", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            let entry = list_append(&mut list, (&42 as *const i32) as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, (&44 as *const i32) as *const c_void);
            b.iter(|| {
                list_remove_entry(&mut list, black_box(entry));
            })
        }
    });

    c.bench_function("list_list_remove_data", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
            b.iter(|| {
                list_remove_data(
                    &mut list,
                    black_box(|a, b| a == b),
                    black_box(&42 as *const c_void),
                );
            })
        }
    });

    c.bench_function("list_list_length", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
            list_append(&mut list, (&42 as *const i32) as *const c_void);
        }
        b.iter(|| {
            unsafe {
                list_length(black_box(list));
            }
        })
    });

    c.bench_function("list_list_sort", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, (&42 as *const i32) as *const c_void);
            list_append(&mut list, (&44 as *const i32) as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        b.iter(|| {
            unsafe {
                list_sort(
                    &mut list,
                    black_box(|a, b| (a as usize).cmp(&(b as usize))),
                );
            }
        })
    });

    c.bench_function("list_list_iter_remove", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        let mut iter = ListIterator {
            prev_next: std::ptr::null_mut(),
            current: std::ptr::null_mut(),
        };
        unsafe {
            list_iterate(&mut list, &mut iter);
            list_iter_next(&mut iter);
        }
        b.iter(|| {
            unsafe {
                list_iter_remove(&mut iter);
            }
        })
    });

    c.bench_function("list_list_to_array", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        b.iter(|| {
            unsafe {
                list_to_array(black_box(list));
            }
        })
    });

    c.bench_function("list_list_find_data", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, (&43 as *const i32) as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        b.iter(|| {
            unsafe {
                list_find_data(
                    black_box(list),
                    black_box(|a, b| a == b),
                    black_box(&42 as *const c_void),
                );
            }
        })
    });

    c.bench_function("list_list_iterate", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, (&42 as *const i32) as *const c_void);
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, (&44 as *const i32) as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        let mut iter = ListIterator {
            prev_next: std::ptr::null_mut(),
            current: std::ptr::null_mut(),
        };
        b.iter(|| {
            unsafe {
                list_iterate(&mut list, &mut iter);
            }
        })
    });

    c.bench_function("list_list_iter_next", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, (&43 as *const i32) as *const c_void);
        }
        let mut iter = ListIterator {
            prev_next: std::ptr::null_mut(),
            current: std::ptr::null_mut(),
        };
        unsafe {
            list_iterate(&mut list, &mut iter);
        }
        b.iter(|| {
            unsafe {
                list_iter_next(&mut iter);
            }
        })
    });

    c.bench_function("list_list_iter_has_more", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, (&42 as *const i32) as *const c_void);
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, (&44 as *const i32) as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        let mut iter = ListIterator {
            prev_next: std::ptr::null_mut(),
            current: std::ptr::null_mut(),
        };
        unsafe {
            list_iterate(&mut list, &mut iter);
        }
    c.bench_function("list_list_iter_remove", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        let mut iter = ListIterator {
            prev_next: std::ptr::null_mut(),
            current: std::ptr::null_mut(),
        };
        unsafe {
            list_iterate(&mut list, &mut iter);
            list_iter_next(&mut iter);
        }
        b.iter(|| {
            unsafe {
                list_iter_remove(&mut iter);
            }
        })
    });

    c.bench_function("list_list_to_array", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        b.iter(|| {
            unsafe {
                list_to_array(black_box(list));
            }
        })
    });

    c.bench_function("list_list_sort", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, (&42 as *const i32) as *const c_void);
            list_append(&mut list, (&44 as *const i32) as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        b.iter(|| {
            unsafe {
                list_sort(
                    &mut list,
                    black_box(|a, b| (a as usize).cmp(&(b as usize))),
                );
            }
        })
    });

    c.bench_function("list_list_find_data", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, (&43 as *const i32) as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        b.iter(|| {
            unsafe {
                list_find_data(
                    black_box(list),
                    black_box(|a, b| a == b),
                    black_box(&42 as *const c_void),
                );
            }
        })
    });

    c.bench_function("list_list_iterate", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, (&42 as *const i32) as *const c_void);
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, (&44 as *const i32) as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        let mut iter = ListIterator {
            prev_next: std::ptr::null_mut(),
            current: std::ptr::null_mut(),
        };
        b.iter(|| {
            unsafe {
                list_iterate(&mut list, &mut iter);
            }
        })
    });

    c.bench_function("list_list_iter_next", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, (&43 as *const i32) as *const c_void);
        }
        let mut iter = ListIterator {
            prev_next: std::ptr::null_mut(),
            current: std::ptr::null_mut(),
        };
        unsafe {
            list_iterate(&mut list, &mut iter);
        }
        b.iter(|| {
            unsafe {
                list_iter_next(&mut iter);
            }
        })
    });

    c.bench_function("list_list_iter_has_more", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, (&42 as *const i32) as *const c_void);
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, (&44 as *const i32) as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        let mut iter = ListIterator {
            prev_next: std::ptr::null_mut(),
            current: std::ptr::null_mut(),
        };
        unsafe {
            list_iterate(&mut list, &mut iter);
        }
        b.iter(|| {
            unsafe {
                list_iter_has_more(&mut iter);
            }
        })
    });
});

    c.bench_function("list_list_to_array", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        b.iter(|| {
            unsafe {
                list_to_array(black_box(list));
            }
        })
    });

    c.bench_function("list_list_sort", |b| {
            list_append(&mut list, (&42 as *const i32) as *const c_void);

        unsafe {
            list_append(&mut list, (&44 as *const i32) as *const c_void);

            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        b.iter(|| {
            unsafe {
                list_sort(
                    &mut list,
                    black_box(|a, b| (a as usize).cmp(&(b as usize))),
                );
            }
        })
    });

    c.bench_function("list_list_find_data", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, (&43 as *const i32) as *const c_void);

            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        b.iter(|| {
            unsafe {
                list_find_data(
                    black_box(list),
                    black_box(|a, b| a == b),
                    black_box(&42 as *const c_void),
                );
            }
        })
    });

    c.bench_function("list_list_iterate", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
            list_append(&mut list, (&42 as *const i32) as *const c_void);

            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, (&44 as *const i32) as *const c_void);

            list_append(&mut list, &44 as *const c_void);
        }
        let mut iter = ListIterator {
            prev_next: std::ptr::null_mut(),
            current: std::ptr::null_mut(),
        };
        b.iter(|| {
            unsafe {
                list_iterate(&mut list, &mut iter);
            }
        })
    });

    c.bench_function("list_list_iter_next", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, (&43 as *const i32) as *const c_void);

        }
        let mut iter = ListIterator {
            prev_next: std::ptr::null_mut(),
            current: std::ptr::null_mut(),
        };
        unsafe {
            list_iterate(&mut list, &mut iter);
        }
        b.iter(|| {
            unsafe {
                list_iter_next(&mut iter);
            }
        })
    });

    c.bench_function("list_list_iter_has_more", |b| {
        let mut list: *mut ListEntry = std::ptr::null_mut();
            list_append(&mut list, (&42 as *const i32) as *const c_void);

            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, (&44 as *const i32) as *const c_void);

            list_append(&mut list, &44 as *const c_void);
        }
        let mut iter = ListIterator {
            prev_next: std::ptr::null_mut(),
            current: std::ptr::null_mut(),
        };
        unsafe {
            list_iterate(&mut list, &mut iter);
        }
        b.iter(|| {
            unsafe {
                list_iter_has_more(&mut iter);
            }
        })
    });

            list_append(&mut list, (&43 as *const i32) as *const c_void);

        let mut list: *mut ListEntry = std::ptr::null_mut();
        unsafe {
            list_append(&mut list, &42 as *const c_void);
            list_append(&mut list, &43 as *const c_void);
            list_append(&mut list, &44 as *const c_void);
        }
        let mut iter = ListIterator {
            prev_next: std::ptr::null_mut(),
            current: std::ptr::null_mut(),
        };
        unsafe {
            list_iterate(&mut list, &mut iter);
            list_iter_next(&mut iter);
        }
        b.iter(|| {
            unsafe {
                list_iter_remove(&mut iter);
            }
            list_append(&mut list, (&42 as *const i32) as *const c_void);

    });
            list_append(&mut list, (&44 as *const i32) as *const c_void);


criterion_group!(benches, list_benchmark);
criterion_main!(benches);
            list_append(&mut list, (&43 as *const i32) as *const c_void);